The following examples represent some possibilities
for customization or extending Microsoft Dynamics CRM when you don’t
need to worry about security outside of your domain.
Example One: Formatting the Phone Number
When entering a phone
number into the system, no formatting logic/mask is applied to the
entered number. Not having a formatting mask is helpful if you need to
enter a phone number and an extension (such as 916-712-5451, ext: 001),
but a properly formatted phone number adds to both human and integrated
system readability.
Figure 1 shows a standard CRM Account form with a freely entered telephone in the Main Phone field.
To add formatting to this field, place the following code in the Account form onLoad event. (Be sure the event is enabled.)
phoneFieldValidationFun = function (source)
{
var oField = source;
if (!IsNull(oField))
{
if(IsNull(oField.DataValue))
{
return;
}
var sUSPhone = oField.DataValue.replace(/[^0-9]/g, "");
// Check the length and format as necessary
switch (sUSPhone.length)
{
case "19167125451".length:
oField.DataValue = "+1 ("+ sUSPhone.substr(1, 3) + ") " + sUSPhone.substr(4, 3) + "-" + sUSPhone.substr(7, 4);
break;
case "9167125451".length:
oField.DataValue = "("+ sUSPhone.substr(0, 3) + ") " + sUSPhone.substr(3, 3) + "-" + sUSPhone.substr(6, 4);
break;
case "167125451".length:
oField.DataValue = "(0"+sUSPhone.substr(0, 2)+") " + sUSPhone.substr(2, 3) + "-" + sUSPhone.substr(5, 4);
break;
case "7125451".length:
oField.DataValue = sUSPhone.substr(0, 3) + "-" + sUSPhone.substr(3,4);
break;
}
}
}
Now place the following code for each phone field (using the onChange event):
phoneFieldValidationFun(event.srcElement);
Applying the preceding code to the onChange event of the fields that need to be formatted with phone numbering will properly format the phone number entry, as shown in Figure 2.
This example clearly shows
how to format data simply and easily on data entry. It would be a
trivial matter to apply error handling and formatting for other fields
by modifying the example shown.
Example Two: Validating Data Across the CRM Application
It is common to
be working with Microsoft Dynamics CRM and need to query/validate
entered data against another entity’s data. A common example is when a
Parent Customer or Primary Contact is selected for the Contact or
Account records, but it could be used in a number of situations. Other
common scenarios include the following:
Populating data on the account for invoice quantities and/or amounts (if you wanted to use CRM to show total orders/amounts)
Updating subordinate records such as Opportunities, Quote, Orders, or Invoices with information entered on the Account level
Modifying Account data based on case status
This example shows how to
check the related Account record of the Contact and validate phone
numbers. If they differ, the system prompts the user as to whether the
user wants to update the Contact record with the main phone number from
the Account.
Place the following code on
the Parent Customer field of the Contact entity using the JavaScript
onChange event to call an asynchronous event to query the CRM database
and update/validate a value based on a user selection:
//Check to see if the parentcustomer is populated
if(crmForm.all.parentcustomerid.DataValue != null)
{
if(crmForm.all.parentcustomerid.DataValue[0].type == '1')
{
var xml = "" +
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
GenerateAuthenticationHeader() +
" <soap:Body>" +
" <RetrieveMultiple
xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
" <query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\"
xsi:type=\"q1:QueryExpression\">" +
//Query against the account entity
" <q1:EntityName>account</q1:EntityName>" +
" <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
" <q1:Attributes>" +
//Check the telephone1 attribute – this can be modified to
//check any of the telephone fields that exist
" <q1:Attribute>telephone1</q1:Attribute>" +
" </q1:Attributes>" +
" </q1:ColumnSet>" +
" <q1:Distinct>false</q1:Distinct>" +
" <q1:Criteria>" +
" <q1:FilterOperator>And</q1:FilterOperator>" +
" <q1:Conditions>" +
" <q1:Condition>" +
" <q1:AttributeName>accountid</q1:AttributeName>" +
" <q1:Operator>Equal</q1:Operator>" +
" <q1:Values>" +
" <q1:Value xsi:type=\"xsd:string\">"+
crmForm.all.parentcustomerid.DataValue[0].id +
" </q1:Value>" +
" </q1:Values>" +
" </q1:Condition>" +
" </q1:Conditions>" +
" </q1:Criteria>" +
" </query>" +
" </RetrieveMultiple>" +
" </soap:Body>" +
"</soap:Envelope>" +
"";
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRe-
quest.setRequestHeader("SOAPAction","http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
var resultXml = xmlHttpRequest.responseXML;
//alert(resultXml.xml);
var accountMainPhone = re
sultXml.selectSingleNode("//BusinessEntity/q1:telephone1");
if(accountMainPhone != null)
{
var contactBusinessPhone = crmForm.all.telephone1;
//Validate the contact business phone against the account phone
if(contactBusinessPhone.DataValue != accountMainPhone.text)
{
//If not equal then prompt to change it
if(confirm("Account Main Phone is not equal to Contact Business
Phone. Would you like to change it?"))
{
//User responded affirmatively, so let's update the contact
//phone with the account phone information
contactBusinessPhone.DataValue = accountMainPhone.text;
}
}
}
}
}
Figure 3
shows what happens when you try to set the Parent Customer of a Contact
record. The code checks the Business Phone of the Contact against the
Main Phone of the Account and prompts for updating of the Contact
record.
This example can easily
be applied across other entities within the CRM system and is a common
request to extend functionality internally.
Example Three: Extending a Form for IFrame Integration
As mentioned
previously, there are several considerations when working with IFrames,
including the fact that IFrames load asynchronously and are shared
across all clients. This example checks whether the user is working
offline, and if not, sets the target of the IFrame dynamically.
Note
It is important to
note that when working with dynamically created IFrames, parameters are
not passed to the new URL automatically and the query string parameters
need to be appended before setting the src property.
To follow this example, create a new IFrame on the Contact entity, and set the URL on the IFrame URL equal to about:blank. This will open the IFrame to a blank page by default.
Modify the onLoad event for the form and add the following code:
Var sURLString = "";
//Validate if the user is offline or not
if(IsOnline())
{
//Check to see if the form is saved or just being created
switch (crmForm.FormType)
{
//Form is being created – we can't pass anything yet
case 1:
//Set to our generic intranet site
sURLString = "http://intranet";
break;
//Form is saved and we have data we can grab
case 2:
//Set to the intranet site with content specific to the contact
sURLString = "http://intranet?contact=";
//encode and add contact information
sURLString += encodeURIComponent(crmFORM.all.name.DataValue);
break;
}
}
//User is not online
else
{
//We can leave the URL as about:blank or change it to an
//internal URL if we want
}
//Finally set the IFrame URL (be sure to replace <<name>> with the name of
//your IFrame:
crmForm.all.IFRAME_<<name>>.src = sURLString;
If the user is online, the intranet site is displayed.